#include "aerial\Game\GameObject\Equipment\VulcanEquip.h"
#include "aerial\Game\GameObject\FlyObject\Fighter.h"

#include "aerial\Game\Helper\BattleHelper.h"

#include "hge\hgecolor.h"

const float VulcanEquip::Speed = 1000.f;
const float VulcanEquip::MinPowerRequire = 30.f;
const float VulcanEquip::MaxRange = 600.f;
const int VulcanEquip::FadeSpeed = 1;

VulcanEquip::VulcanEquip(b2World* _world, Fighter* _host)
	: Equipment(), max_range(MaxRange), vulcanEquipState(Off), world(_world), host(_host)
{
	VRCC = new VulcanRayCastCallback(this);
	
	t_range = 0.f;
	b2Vec2 T;

	psInner = new hgeParticleSystem(&hgeResMan->GetParticleSystem("ps.vulcan.inner")->info);
	psInner->info.fSizeStart = 2.0;
	psInner->info.colColorStart.r = 1.0;
	psInner->info.colColorStart.g = 1.0;
	psInner->info.colColorStart.b = 1.0;
	
	psInner->info.colColorEnd.r = 1.0;
	psInner->info.colColorEnd.g = 1.0;
	psInner->info.colColorEnd.b = 1.0;

	psInner->info.nEmission = 100;
	psInner->info.fParticleLifeMin = 2.3f;

	psOuter = new hgeParticleSystem(&hgeResMan->GetParticleSystem("ps.vulcan.outer")->info);
	psOuter->info.colColorStart.r = 0;
	psOuter->info.colColorStart.g = 0;
	psOuter->info.colColorStart.b = 1.0;
	
	psOuter->info.colColorEnd.r = 0;
	psOuter->info.colColorEnd.g = 0;
	psOuter->info.colColorEnd.b = 1.0;

	psOuter->info.nEmission = 100;
	psOuter->info.fParticleLifeMin = 2.3f;

	psInner->FireAt(T.x, T.y);
	psOuter->FireAt(T.x, T.y);
}

bool VulcanEquip::available() {	
	return host->GetPower() > MinPowerRequire; 
}

void VulcanEquip::renderVulcan()
{
	if (vulcanEquipState != Off) 
	{
		psOuter->Render();
		psInner->Render();
	}
}

bool VulcanEquip::update(float dt)
{
	if (vulcanEquipState != Off)
	{
		if (vulcanEquipState == On)
		{
			b2Vec2 _Ts = BattleHelper::getBox2dCoordinateFromHge(Ts);
			b2Vec2 _Td = BattleHelper::getBox2dCoordinateFromHge(Td);
			world->RayCast(VRCC, _Ts, _Td);
		}
		else if (vulcanEquipState == Fade) 
		{
			psInner->info.nEmission -= FadeSpeed;
			psOuter->info.nEmission -= FadeSpeed;
	
			if (psInner->info.nEmission <= 0) 
			{
				vulcanEquipState = Off;
				psInner->info.nEmission = 0;
				psOuter->info.nEmission = 0;
				return true;
			}
		}
		t_range += Speed * dt;
		if (t_range > max_range) t_range = 0.f;

		psInner->MoveTo(Ts.x + D.x * t_range, Ts.y + D.y * t_range);
		psOuter->MoveTo(Ts.x + D.x * t_range, Ts.y + D.y * t_range);
		psOuter->Update(dt);
		psInner->Update(dt);
	}
	return false;
}

void VulcanEquip::start()
{
	max_range = MaxRange;
	vulcanEquipState = On;
	host->UsePower(MinPowerRequire);
	Ts = host->GetPosition();
	D = host->GetDirection();
	Td.Set(
		Ts.x + MaxRange * D.x,
		Ts.y + MaxRange * D.y
		);

	psInner->info.nEmission = 100;
	psOuter->info.nEmission = 100;
	psInner->MoveTo(Ts.x, Ts.y);
	psOuter->MoveTo(Ts.x, Ts.y);
}

void VulcanEquip::Hit(float fraction)
{
	max_range = MaxRange * fraction;
}

void VulcanEquip::stop()
{
	if (vulcanEquipState != Off) vulcanEquipState = Fade;
}

bool VulcanEquip::isOn()
{
	return vulcanEquipState == On;
}

VulcanEquip::~VulcanEquip()
{
	delete psInner;
	delete psOuter;
}

float32 VulcanRayCastCallback::ReportFixture(b2Fixture *fixture,  const b2Vec2& point,  const b2Vec2& normal, float32 fraction)
{
	m_fixture = fixture;
	m_point = point;
	m_normal = normal;
	m_fraction = fraction;
	if (!fixture->GetBody()->GetUserData()) return 1;
	GameObject* gObj = (GameObject*)fixture->GetBody()->GetUserData();

	if (gObj->GetObjectType() == TYPE_FLY)
	{
		FlyObject* fObj = (FlyObject*)gObj;
		if (fObj->side == vulcanEquip->host->side) return 0;
		else 
		{
			vulcanEquip->Hit(fraction);
			fObj->TakeEffect(vulcanEquip);
			return fraction;
		}
	}
	else return 0;
}